***** STATA version 16.1
* Creates tables and figures using official election results
* original data source: Electoral Affairs Commission
* URL: https://www.eac.hk/en/legco/lce.htm
* 
*
* tables: 1, C1, E1
* figures: 1 (right panel), 2, D1

clear all
set more off

***** additional packages required to run the code, uncomment to install
// ssc install blindschemes, replace
// ssc install mplotoffset, replace
// ssc install addplot, replace
// ssc install estout, replace

cd "/path/to/current/directory/"

set scheme plotplain
set seed 495225107 /// from random.org

************ load data
use "election_data.dta", clear

*** create folders if not already existed
capture mkdir "figures"
capture mkdir "tables"

*** declare panel variable
xtset station

*** Figure 1, right panel
* Note: left panel was created with QGIS with shapefiles provided by Registration and Electoral Office, HKSAR

preserve
keep if election==201609|election==201803
egen election_opposition = concat(election opposition), punct("_")
keep election_opposition eshare station 
reshape wide eshare, i(station) j(election_opposition) string

twoway (scatter eshare201803_1 eshare201609_1, color("229 178 0 %70") msymbol(S)) ///
	(scatter eshare201803_0 eshare201609_0, color(ebblue %70)) ///
	(function x, range(0 0.5) n(2)), ///
	legend(label(1 "Opposition camp") label(2 "Establishment camp") order(1 2) position(6) row(1)) ///
	ytitle("Electorate share in March 2018") xtitle("Electorate share in September 2016") ///
	ysize(8) xsize(8) scale(0.8)
graph export "figures/figure 1 right.png", replace

restore

****** main result (Table 1 model 1-2, Figure 2)
* for scatterplots
generate byelection_shifted1 = byelection + cond(opposition, .05, -.05)
generate byelection_shifted3 = byelection + cond(opposition, .05, -.25) + p_radical_3*0.1
label values byelection_shifted1 byelection
label values byelection_shifted3 byelection

* model 1
regress eshare i.opposition##i.byelection if match2==1 & postdq==1, vce(cluster station)
estimates store main_1

* figure 2 (left panel)
margins, at(opposition=(0 1) byelection=(0 1))
mplotoffset, xdimension(byelection) xlabel(,labsize(*1.5)) offset(.1) ///
	plot1opts(mcolor(ebblue) msymbol(Oh) lcolor(ebblue) lpattern(solid)) ci1opts(lcolor(ebblue)) ///
	plot2opts(mcolor("229 178 0") msymbol(S) lcolor("229 178 0") lpattern(solid)) ci2opts(lcolor("229 178 0")) ///
	title("All matched counting stations", size(large)) ///
	legend(position(6)) ///
	ytitle("Electorate share", size(large)) xtitle("") name("main_1", replace)

addplot: (scatter eshare byelection_shifted1 if opposition==0 & match2==1 & postdq==1, ///
			jitter(3) msize(1pt) mcolor(ebblue%20) msymbol(Oh)) || ///
		(scatter eshare byelection_shifted1 if opposition==1 & match2==1 & postdq==1, ///
			jitter(3) msize(1pt) mcolor("229 178 0 %20") msymbol(S)) , below  ///
	legend(order(3 "Establishment" 4 "Opposition")) ///
	yscale(range(0 0.5)) ylabel(0(0.1)0.5) ///
	xscale(range(-.5 1.5)) xlabel(0 1)

* model 2
regress eshare i.opposition##i.byelection##i.p_radical_3 ///
	if match2==1 & postdq==1, vce(cluster station)
estimates store main_3

* figure 2 (right panel)
margins opposition#byelection#p_radical_3
mplotoffset, xdimension(byelection) xlabel(,labsize(*1.5)) offset(.1) ///
	plot1opts(mcolor(ebblue) msymbol(Oh) lcolor(ebblue) lpattern(solid)) ci1opts(lcolor(ebblue)) ///
	plot2opts(mcolor(ebblue*1.5) msymbol(Oh) lcolor(ebblue*1.5) lpattern("-")) ci2opts(lcolor(ebblue*1.5)) ///
	plot3opts(mcolor(ebblue*2) msymbol(Oh) lcolor(ebblue*2) lpattern("-.")) ci3opts(lcolor(ebblue*2)) ///
	plot4opts(mcolor("229 178 0") msymbol(S) lcolor("229 178 0") lpattern(solid)) ci4opts(lcolor("229 178 0")) ///
	plot5opts(mcolor("229 178 0 *1.5") msymbol(S) lcolor("229 178 0 *1.5") lpattern("-")) ci5opts(lcolor("229 178 0 *1.5")) ///
	plot6opts(mcolor("229 178 0 *2") msymbol(S) lcolor("229 178 0 *2") lpattern("-.")) ci6opts(lcolor("229 178 0 *2")) ///
	legend(position(6) col(2) colfirst) ///
	title("Counting stations separated by level of radical support", size(large)) ///
	ytitle("Electorate share", size(large)) xtitle("") name("main_3", replace)

addplot: (scatter eshare byelection_shifted3 if opposition==0 & match2==1 & p_radical_3==0 & postdq==1, ///
			jitter(3) msize(1pt) mcolor(ebblue%20) msymbol(Oh)) || ///
		(scatter eshare byelection_shifted3 if opposition==0 & match2==1 & p_radical_3==1 & postdq==1, ///
			jitter(3) msize(1pt) mcolor(ebblue*1.5%20) msymbol(Oh)) || ///
		(scatter eshare byelection_shifted3 if opposition==0 & match2==1 & p_radical_3==2 & postdq==1, ///
			jitter(3) msize(1pt) mcolor(ebblue*2%20) msymbol(Oh)) || ///
		(scatter eshare byelection_shifted3 if opposition==1 & match2==1 & p_radical_3==0 & postdq==1, ///
			jitter(3) msize(1pt) mcolor("229 178 0 %20") msymbol(S)) || ///
		(scatter eshare byelection_shifted3 if opposition==1 & match2==1 & p_radical_3==1 & postdq==1, ///
			jitter(3) msize(1pt) mcolor("229 178 0 %20 *1.5") msymbol(S)) || ///
		(scatter eshare byelection_shifted3 if opposition==1 & match2==1 & p_radical_3==2 & postdq==1, ///
			jitter(3) msize(1pt) mcolor("229 178 0 %20 *2") msymbol(S)), below ///
	legend(order(- "{bf:Establishment}" - "Radical support:" 7 "Low" 8 "Medium" 9 "High" ///
		- - "{bf:Opposition}" - "Radical support:" 10 "Low" 11 "Medium" 12 "High")) ///
	yscale(range(0 0.5)) ylabel(0(0.1)0.5) ///
	xscale(range(-.5 1.5)) xlabel(0 1)

* create figure 2
graph combine main_1 main_3, row(1) ysize(4) xsize(8) name(DID)
graph export "figures/figure 2.png", replace

***** placebo test (Table 1 model 3-4, Figure D1)
* for scatterplots
replace byelection_shifted3 = byelection + cond(opposition, .05, -.25) + p_radical_3_201209*0.1
label values byelection_shifted3 byelection

* model 3
regress eshare i.opposition##i.byelection if match2==1 & postdq==0, vce(cluster station)
estimates store placebo_1

* figure D1 (left panel)
margins, at(opposition=(0 1) byelection=(0 1))
mplotoffset, xdimension(byelection) xlabel(,labsize(*1.5)) offset(.1) ///
	plot1opts(mcolor(ebblue) msymbol(Oh) lcolor(ebblue) lpattern(solid)) ci1opts(lcolor(ebblue)) ///
	plot2opts(mcolor("229 178 0") msymbol(S) lcolor("229 178 0") lpattern(solid)) ci2opts(lcolor("229 178 0")) ///
	title("All matched counting stations", size(large)) ///
	legend(position(6)) ///
	ytitle("Electorate share", size(large)) xtitle("") name("placebo_1", replace)

addplot: (scatter eshare byelection_shifted1 if opposition==0 & match2==1 & postdq==0, ///
			jitter(3) msize(1pt) mcolor(ebblue%20) msymbol(Oh)) || ///
		(scatter eshare byelection_shifted1 if opposition==1 & match2==1 & postdq==0, ///
			jitter(3) msize(1pt) mcolor("229 178 0 %20") msymbol(S)) , below  ///
	legend(order(3 "Establishment" 4 "Opposition")) ///
	yscale(range(0 0.5)) ylabel(0(0.1)0.5) ///
	xscale(range(-.5 1.5)) xlabel(0 1)

* model 4
regress eshare i.opposition##i.byelection##i.p_radical_3_201209 ///
	if match2==1 & postdq==0, vce(cluster station)
estimates store placebo_3

* figure D1 (right panel)
margins opposition#byelection#p_radical_3_201209
mplotoffset, xdimension(byelection) xlabel(,labsize(*1.5)) offset(.1) ///
plot1opts(mcolor(ebblue) msymbol(Oh) lcolor(ebblue) lpattern(solid)) ci1opts(lcolor(ebblue)) ///
	plot2opts(mcolor(ebblue*1.5) msymbol(Oh) lcolor(ebblue*1.5) lpattern("-")) ci2opts(lcolor(ebblue*1.5)) ///
	plot3opts(mcolor(ebblue*2) msymbol(Oh) lcolor(ebblue*2) lpattern("-.")) ci3opts(lcolor(ebblue*2)) ///
	plot4opts(mcolor("229 178 0") msymbol(S) lcolor("229 178 0") lpattern(solid)) ci4opts(lcolor("229 178 0")) ///
	plot5opts(mcolor("229 178 0 *1.5") msymbol(S) lcolor("229 178 0 *1.5") lpattern("-")) ci5opts(lcolor("229 178 0 *1.5")) ///
	plot6opts(mcolor("229 178 0 *2") msymbol(S) lcolor("229 178 0 *2") lpattern("-.")) ci6opts(lcolor("229 178 0 *2")) ///
	legend(position(6) col(2) colfirst) ///
	title("Counting stations separated by level of radical support", size(large)) ///
	ytitle("Electorate share", size(large)) xtitle("") name("placebo_3", replace)

addplot: (scatter eshare byelection_shifted3 if opposition==0 & match2==1 & p_radical_3_201209==0 & postdq==0, ///
			jitter(3) msize(1pt) mcolor(ebblue%20) msymbol(Oh)) || ///
		(scatter eshare byelection_shifted3 if opposition==0 & match2==1 & p_radical_3_201209==1 & postdq==0, ///
			jitter(3) msize(1pt) mcolor(ebblue*1.5%20) msymbol(Oh)) || ///
		(scatter eshare byelection_shifted3 if opposition==0 & match2==1 & p_radical_3_201209==2 & postdq==0, ///
			jitter(3) msize(1pt) mcolor(ebblue*2%20) msymbol(Oh)) || ///
		(scatter eshare byelection_shifted3 if opposition==1 & match2==1 & p_radical_3_201209==0 & postdq==0, ///
			jitter(3) msize(1pt) mcolor("229 178 0 %20") msymbol(S)) || ///
		(scatter eshare byelection_shifted3 if opposition==1 & match2==1 & p_radical_3_201209==1 & postdq==0, ///
			jitter(3) msize(1pt) mcolor("229 178 0 %20 *1.5") msymbol(S)) || ///
		(scatter eshare byelection_shifted3 if opposition==1 & match2==1 & p_radical_3_201209==2 & postdq==0, ///
			jitter(3) msize(1pt) mcolor("229 178 0 %20 *2") msymbol(S)), below ///
	legend(order(- "{bf:Establishment}" - "Radical support:" 7 "Low" 8 "Medium" 9 "High" ///
		- - "{bf:Opposition}" - "Radical support:" 10 "Low" 11 "Medium" 12 "High")) ///
	yscale(range(0 0.5)) ylabel(0(0.1)0.5) ///
	xscale(range(-.5 1.5)) xlabel(0 1)

* create figure D1
graph combine placebo_1 placebo_3, row(1) ysize(4) xsize(8) name(PCB)
graph export "figures/figure D1.png", replace

* create table 1
esttab main_1 main_3 placebo_1 placebo_3 using "tables/table 1.rtf", ///
	b(%9.3f) se(%9.3f) nobaselevels nonote nomtitles nogaps ///
	refcat(1.p_radical_3_201209 "(ref: Radical proportion low)", nolabel) ///
	addnote("Cluster robust standard errors in parentheses" "* p < 0.05, ** p < 0.01, *** p < 0.001") ///
	label interaction(" x ") replace

	
***** repeat table 1 with LSD classified as moderate
* table E1
regress eshare i.opposition##i.byelection##i.p_radical_3_alt ///
	if match2==1 & postdq==1, vce(cluster station)
estimates store main_3_alt

regress eshare i.opposition##i.byelection##i.p_radical_3_201209_alt ///
	if match2==1 & postdq==0, vce(cluster station)
estimates store placebo_3_alt

esttab main_1 main_3_alt placebo_1 placebo_3_alt using "tables/table E1.rtf", ///
	b(%9.3f) se(%9.3f) nobaselevels nonote nomtitles nogaps ///
	refcat(1.p_radical_3_201209 "(ref: Radical proportion low)", nolabel) ///
	addnote("Cluster robust standard errors in parentheses" "* p < 0.05, ** p < 0.01, *** p < 0.001") ///
	label interaction(" x ") replace

	
